package common.tool.box.utils.json;

import com.alibaba.fastjson2.JSONObject;
import com.alibaba.fastjson2.JSONWriter;
import com.alibaba.fastjson2.TypeReference;
import common.tool.box.common.constant.Constants;
import common.tool.box.common.core.domain.model.JsonFormatParam;
import common.tool.box.common.core.domain.model.JsonMockVo;
import common.tool.box.common.enums.JsonOperationType;
import common.tool.box.generator.domain.GenTable;
import common.tool.box.generator.domain.GenTableColumn;
import common.tool.box.generator.util.VelocityInitializer;
import common.tool.box.generator.util.VelocityUtils;
import net.andreinc.mockneat.MockNeat;
import org.apache.commons.compress.utils.Lists;
import org.apache.velocity.Template;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.Velocity;

import java.io.StringWriter;
import java.util.Date;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

public class JsonFormatUtils {
    /**
     * 字符串转格式化JSON
     */
    public static String formatJson(JsonFormatParam jsonFormatParam) {
        // 随机生成json type=0
        if (JsonOperationType.MOCK.matches(jsonFormatParam.getType())) {
            return mockJson();
        }
        // 格式化json字符串 type=1
        if (JsonOperationType.STRING_TO_JSON.matches(jsonFormatParam.getType())) {
            return stringToJson(jsonFormatParam.getTextArea());
        }
        // 压缩json字符串 type=2
        if (JsonOperationType.JSON_TO_STRING.matches(jsonFormatParam.getType())) {
            return jsonToString(jsonFormatParam.getTextArea());
        }
        // json字符串转义 type=3
        if (JsonOperationType.JSON_ESCAPE.matches(jsonFormatParam.getType())) {
            return jsonEscape(jsonFormatParam.getTextArea());
        }
        // json字符串反转义 type=4
        if (JsonOperationType.JSON_UNESCAPE.matches(jsonFormatParam.getType())) {
            return jsonUnescape(jsonFormatParam.getTextArea());
        }
        if (JsonOperationType.JSON_TO_Java.matches(jsonFormatParam.getType())) {
            return json2Java(jsonFormatParam);
        }
        return "";
    }

    /**
     * 随机生成json字符串
     * type=0
     */
    public static String mockJson() {
        MockNeat mock = MockNeat.threadLocal();
        JsonMockVo json = mock
                .reflect(JsonMockVo.class)
                .field("text", mock.strings().size(10).val())
                .field("number", mock.ints().range(0, 100).val())
                .field("doubleNumber", mock.doubles().range(0, 100).val())
                .field("floatNumber", mock.floats().range(0, 100).val())
                .field("bool", mock.bools().val())
                .field("array", mock.strings().size(10).array(String.class, 10).val())
                .field("object", mock.reflect(JsonFormatParam.class).val())
                .field("date", new Date())
                .field("image", "https://gw.alipayobjects.com/zos/rmsportal/KDpgvguMpGfqaHPjicRK.svg")
                .field("color", "#ff0000")
                .field("email", mock.emails().val())
                .field("ipv4", mock.ipv4s().val())
                .field("actresses", mock.actresses().val())
                .val();
        return stringToJson(JSONObject.toJSONString(json));
    }

    /**
     * 字符串转格式化JSON
     * type=1
     */
    public static String stringToJson(String jsonStr) {
        JSONObject jsonObject = JSONObject.parseObject(jsonStr);
        String prettyJson = JSONObject.toJSONString(jsonObject
                // 格式化
                , JSONWriter.Feature.PrettyFormat
                // 允许空字段
                , JSONWriter.Feature.WriteNulls);
        return prettyJson;
    }

    /**
     * JSON格式化转字符（压缩）
     * type=2
     */
    public static String jsonToString(String jsonStr) {
        return jsonStr.replaceAll("\n", "").replaceAll("\t", "").replaceAll(" ", "");
    }

    /**
     * JSON字符转义
     * type=3
     */
    public static String jsonEscape(String jsonStr) {
        return jsonStr.replaceAll("\"", "\\\\\"");
    }

    /**
     * JSON字符反转义
     * type=4
     */
    public static String jsonUnescape(String jsonStr) {
        return jsonStr.replaceAll("\\\\\"", "\"");
    }

    /**
     * JSON转Java
     * type=5
     */
    public static String json2Java(JsonFormatParam jsonFormatParam) {
        Map<String, String> dataMap = new LinkedHashMap<>();

        Map<String, Object> map = JSONObject.parseObject(jsonFormatParam.getTextArea(), new TypeReference<Map<String,Object>>(){});

        // 填充表信息
        GenTable table = new GenTable();
        table.setClassName(Constants.ENTITY);
        List<GenTableColumn> columns = Lists.newArrayList();
        // 遍历map
        for (Map.Entry<String, Object> entry : map.entrySet()) {
            String key = entry.getKey();
            Object value = entry.getValue();
            // 填充列信息
            GenTableColumn column = new GenTableColumn();
            column.setColumnName(key);
            column.setJavaType(value.getClass().getSimpleName());
            column.setJavaField(key);
            columns.add(column);
        }
        table.setColumns(columns);

        VelocityInitializer.initVelocity();

        VelocityContext context = VelocityUtils.prepareJson2Java(table, jsonFormatParam);

        // 获取模板列表
        List<String> templates = VelocityUtils.getJsonTemplateList();
        for (String template : templates)
        {
            // 渲染模板
            StringWriter sw = new StringWriter();
            Template tpl = Velocity.getTemplate(template, Constants.UTF8);
            tpl.merge(context, sw);
            dataMap.put(template, sw.toString());
        }
        return dataMap.get(templates.get(0));
    }
}
